package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Quad;

public class Main extends SimpleApplication implements AnalogListener {

    private float frustumSize = 20;

    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }

    public void simpleInitApp() {
        createBackground();
        createBox(new Vector3f(3, 0, 0), ColorRGBA.Red);
        createBox(new Vector3f(0, 3, 0), ColorRGBA.Blue);
        createBox(new Vector3f(0, 0, 3), ColorRGBA.Green);
        createDirectionalLight();
        createCamera();

        /*
         * This is some ghetto key bindings to see effects of different
         * modifactions
         */
        inputManager.addListener(this, "Size+", "Size-", "1", "2", "3", "4", "5", "6");
        inputManager.addMapping("Size+", new KeyTrigger(KeyInput.KEY_W));
        inputManager.addMapping("Size-", new KeyTrigger(KeyInput.KEY_S));
        inputManager.addMapping("1", new KeyTrigger(KeyInput.KEY_1));
        inputManager.addMapping("2", new KeyTrigger(KeyInput.KEY_2));
        inputManager.addMapping("3", new KeyTrigger(KeyInput.KEY_3));
        inputManager.addMapping("4", new KeyTrigger(KeyInput.KEY_4));
        inputManager.addMapping("5", new KeyTrigger(KeyInput.KEY_5));
        inputManager.addMapping("6", new KeyTrigger(KeyInput.KEY_6));
    }

    private void createCamera() {
        /*
         * Switch to parallel projection from Orthogonal
         */
        cam.setParallelProjection(true);

        /*
         * Setup view port and perspective (Frustrum)
         */
        float aspect = (float) cam.getWidth() / cam.getHeight();
        cam.setFrustum(-100, 100, -aspect * frustumSize, aspect * frustumSize, frustumSize, -frustumSize);

        /*
         * Switch to (true) isometric view
         */
        cam.setLocation(new Vector3f(1.0f, 1.0f, 1.0f));
        cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Z);
    }

    private void createDirectionalLight() {
        /*
         * Light left side and top
         */
        DirectionalLight dl = new DirectionalLight();
        dl.setColor(ColorRGBA.White);
        dl.setDirection(new Vector3f(-1.0f, 0.0f, -1.0f));
        rootNode.addLight(dl);

        /*
         * Light right side and top
         */
        DirectionalLight dl2 = new DirectionalLight();
        dl2.setColor(ColorRGBA.White);
        dl2.setDirection(new Vector3f(0.0f, -1.0f, -1.0f));
        rootNode.addLight(dl2);

        /*
         * Light the back
         */
        DirectionalLight dl3 = new DirectionalLight();
        dl3.setColor(ColorRGBA.LightGray);
        dl3.setDirection(new Vector3f(1.0f, 1.0f, 0.0f));
        rootNode.addLight(dl3);
    }
    Geometry cubeGeo;

    private void createBox(Vector3f loc, ColorRGBA col) {
        cubeGeo = new Geometry("box", new Box(loc, 1f, 1f, 1f));

        Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");

        /*
         * Toggle this on and off to see cube color layer over texture.
         */
        mat.setBoolean("UseMaterialColors", true);
        mat.setColor("Diffuse", col);

        mat.setTexture("DiffuseMap", assetManager.loadTexture("Textures/grass.jpg"));

        cubeGeo.setMaterial(mat);
        rootNode.attachChild(cubeGeo);
    }

    /*
     * Handlers for ghetto key bindings
     */
    public void onAnalog(String name, float value, float tpf) {
        if (name.equals("Size-")) {
            frustumSize += 0.3f * tpf;
        } else if (name.equals("Size+")) {
            frustumSize -= 0.3f * tpf;
        } else if (name.equals("1")) {
            /*
             * Move down in Z axis
             */
            cubeGeo.move(new Vector3f(0, 0f, -0.01f));
        } else if (name.equals("2")) {
            /*
             * Move up in Z axis
             */
            cubeGeo.move(new Vector3f(0f, 0f, 0.01f));
        } else if (name.equals("3")) {
            /*
             * Move left in X axis
             */
            cubeGeo.move(new Vector3f(-0.01f, 0f, 0f));
        } else if (name.equals("4")) {
            /*
             * Move right in Z axies
             */
            cubeGeo.move(new Vector3f(0.01f, 0f, 0f));
        } else if (name.equals("5")) {
            /*
             * Move up in Y axies
             */
            cubeGeo.move(new Vector3f(0f, -0.01f, 0f));
        } else if (name.equals("6")) {
            /*
             * Move down in Y axies
             */
            cubeGeo.move(new Vector3f(0f, 0.01f, 0f));
        }

        /*
         * Recalculate aspect ratio and Frustrum when we Size- and Size+ (zoom)
         */
        float aspect = (float) cam.getWidth() / cam.getHeight();
        cam.setFrustum(-1000, 1000, -aspect * frustumSize, aspect * frustumSize, frustumSize, -frustumSize);
    }

    private void createBackground() {
        /*
         * Resize background based on view port size
         */
        float bgHeight = frustumSize * 5;
        float bgWidth = bgHeight;

        Geometry bg_geo = new Geometry("bg", new Quad(bgHeight, bgWidth, false));
        Material bg_mat = new Material(assetManager, "Materials/Unshaded.j3md");
        bg_mat.setTexture("ColorMap", assetManager.loadTexture("Textures/starfield.png"));
        bg_geo.setMaterial(bg_mat);

        rootNode.attachChild(bg_geo);

        /*
         * Move it so Quad center is at 0,0
         */
        bg_geo.move(new Vector3f(-bgHeight / 2, -bgWidth / 2, 0.0f));
        /*
         * Render thsi below everything by ordering to last in render queue
         */
        bg_geo.setQueueBucket(Bucket.Sky);
    }
}